﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace WebChatApi.Common
{
    /// <summary>
    /// 
    /// </summary>
    public sealed class EncodingUtil : Singleton<EncodingUtil>
    {
        private static Random random = new Random();

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="EncodingUtil"/> class.
        /// </summary>
        public EncodingUtil() { }

        #endregion

        private char[] alpha = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

        #region Get random string

        /// <summary>
        /// Gets the random number only.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public string GetRandomNumberOnly(int length)
        {
            StringBuilder sb = new StringBuilder();
            sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(alpha[random.Next(10)]);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Gets the random hex string.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public string GetRandomHexString(int length)
        {

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(alpha[random.Next(0, 16)]);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Gets the random hex.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public byte[] GetRandomHex(int length)
        {
            byte[] result = new byte[length];

            for (int i = 0; i < length; i++)
            {
                StringBuilder sb = new StringBuilder();

                sb.Append(alpha[random.Next(0, 16)]);
                sb.Append(alpha[random.Next(0, 16)]);

                result[i] = Convert.ToByte(sb.ToString(), 16);
            }
            return result;
        }

        /// <summary>
        /// Gets the random string.
        /// </summary>
        /// <param name="length">The length.</param>
        /// <returns></returns>
        public string GetRandomString(int length)
        {

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(alpha[random.Next(36)]);
            }
            return sb.ToString();

        }

        #endregion

        #region MD5

        /// <summary>
        /// Encrypts to M d5.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public string EncryptToMD5(string input)
        {
            byte[] data = Encoding.Default.GetBytes(input);
            return EncryptToMD5(data).ToUpperInvariant();
        }


        /// <summary>
        /// Encrypts to M d5.
        /// </summary>
        /// <param name="bytes">The bytes.</param>
        /// <returns></returns>
        /// <exception cref="OperationFailureException">EncodeFileToMD5</exception>
        public string EncryptToMD5(byte[] bytes)
        {
            try
            {
                MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
                byte[] hash_byte = md5Provider.ComputeHash(bytes);
                string result = System.BitConverter.ToString(hash_byte);
                return result.Replace("-", "").ToUpperInvariant();
            }
            catch (Exception ex)
            {
                throw new OperationFailureException("EncryptToMD5", ex, bytes);
            }
        }

        #endregion

        #region SHA1

        /// <summary>
        /// Encrypts to SHA1.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public string EncryptToSHA1(string input)
        {
            return EncryptToSHA1(Encoding.UTF8.GetBytes(input));
        }

        /// <summary>
        /// Encrypts to SH a1.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public string EncryptToSHA1(byte[] data)
        {
            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
            {
                var hash_byte = sha1.ComputeHash(data);
                string result = System.BitConverter.ToString(hash_byte);
                return result.Replace("-", "").ToUpperInvariant();
            }
        }


        #endregion

        #region Base64

        /// <summary>
        /// Encodes the base64 authentication f8.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <returns>System.String.</returns>
        public string EncodeBase64UTF8(string source)
        {
            return EncodeBase64FromString(source, Encoding.UTF8);
        }

        /// <summary>
        /// Encodes the base64 from string.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <returns>System.String.</returns>
        public string EncodeBase64FromString(string source)
        {
            return EncodeBase64FromString(source, Encoding.Default);
        }

        /// <summary>
        /// Encodes the base64 from string.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="encoding">The encoding.</param>
        /// <returns>System.String.</returns>
        public string EncodeBase64FromString(string source, Encoding encoding)
        {
            try
            {
                byte[] bytes = encoding.GetBytes(source);
                return Convert.ToBase64String(bytes);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Encodes the base64 from bytes.
        /// </summary>
        /// <param name="bytes">The bytes.</param>
        /// <returns></returns>
        public string EncodeBase64FromBytes(byte[] bytes)
        {
            try
            {
                return Convert.ToBase64String(bytes);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Decodes the base64 authentication f8.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <returns>System.String.</returns>
        public string DecodeBase64UTF8(string result)
        {
            return DecodeBase64ToString(result, Encoding.UTF8);
        }

        /// <summary>
        /// Decodes the base64 automatic string.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <returns>System.String.</returns>
        public string DecodeBase64ToString(string result)
        {
            return DecodeBase64ToString(result, Encoding.Default);
        }

        /// <summary>
        /// Decodes the base64 to string.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="encoding">The encoding.</param>
        /// <returns>System.String.</returns>
        public string DecodeBase64ToString(string result, Encoding encoding)
        {
            try
            {
                byte[] bytes = Convert.FromBase64String(result);
                return encoding.GetString(bytes);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Decodes the base64 to bytes.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <returns></returns>
        public byte[] DecodeBase64ToBytes(string result)
        {
            try
            {
                byte[] bytes = Convert.FromBase64String(result);
                return bytes;
            }
            catch
            {
                return null;
            }
        }

        #endregion

        /// <summary>
        /// Encodes the string to unicode.
        /// </summary>
        /// <param name="srcText">The SRC text.</param>
        /// <returns></returns>
        public string EncodeStringToUnicode(string srcText)
        {
            return System.Web.HttpUtility.UrlEncode(srcText);
        }

        /// <summary>
        /// Decodes the unicode to string.
        /// </summary>
        /// <param name="srcText">The SRC text.</param>
        /// <returns></returns>
        public string DecodeUnicodeToString(string srcText)
        {
            return System.Web.HttpUtility.UrlDecode(srcText);
        }

        /// <summary>
        /// Generates the name of the upload file.
        /// </summary>
        /// <param name="suffixRndLength">Length of the suffix RND.</param>
        /// <returns></returns>
        public string GenerateUploadFileName(int suffixRndLength)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString("00") + DateTime.Now.Day.ToString("00"));
            sb.Append(DateTime.Now.Hour.ToString("00") + DateTime.Now.Minute.ToString("00") + DateTime.Now.Second.ToString("00"));
            sb.Append(DateTime.Now.Millisecond.ToString("000"));
            sb.Append(GetRandomString(suffixRndLength));
            return sb.ToString();
        }
    }
}
